﻿using System.Collections.Generic;
using System.Linq;
using Framework.DataObjects;
using Framework.FluentDictionary;

namespace Framework.FluentTextStringBuilder.ExtensionXml
{
    // Fluent Text String Builder
    public static class XmlFtsbExtensions
    {
        private const string KeyHierarchy = "XmlFtsbExtensions.XmlHierarchy";

        /// <summary>
        /// XML Element Begin
        /// </summary>
        /// <param name="builder">The builder.</param>
        /// <param name="elementName">Name of the element.</param>
        /// <returns></returns>
        /// <remarks>
        /// StartOfBlock
        /// {
        /// ItemInBlock
        /// </remarks>
        public static ITextStringBuilderWriterFluent XmlElementOpen(this ITextStringBuilderWriterFluent builder, string elementName)
        {
            var stack = GetXmlHierarchy(builder);

            stack.Push(elementName);

            builder
                .AddLine("<{0}>", elementName)
                .IndentRight();

            return builder;
        }

        public static ITextStringBuilderWriterFluent XmlElementOpen(this ITextStringBuilderWriterFluent builder, string elementName, IDictionaryFluent attributes)
        {
            return XmlElementOpen(builder, elementName, attributes.AsDictionary());
        }

        public static ITextStringBuilderWriterFluent XmlElementOpen(this ITextStringBuilderWriterFluent builder, string elementName, IEnumerable<KeyValuePair<string, string>> attributes)
        {
            var stack = GetXmlHierarchy(builder);

            stack.Push(elementName);

            builder
                .Add("<{0}", elementName);

            foreach (var attribute in attributes.Where(attribute => attribute.Value != null))
            {
                builder.Add(" {0}=\"{1}\"", attribute.Key, attribute.Value);
            }

            builder
                .AddLine(">")
                .IndentRight();

            return builder;
        }

        public static ITextStringBuilderWriterFluent XmlElementOpenClose(this ITextStringBuilderWriterFluent builder, string elementName)
        {
            builder
                .AddLine("<{0} />", elementName);

            return builder;
        }

        public static ITextStringBuilderWriterFluent XmlElementOpenClose(this ITextStringBuilderWriterFluent builder, string elementName, IDictionaryFluent attributes)
        {
            return XmlElementOpenClose(builder, elementName, attributes.AsDictionary());
        }

        public static ITextStringBuilderWriterFluent XmlElementOpenClose(this ITextStringBuilderWriterFluent builder, string elementName, IEnumerable<KeyValuePair<string, string>> attributes)
        {
            builder
                .Add("<{0}", elementName);

            foreach (var attribute in attributes.Where(attribute => Is.NotEmptyString(attribute.Value)))
            {
                builder.Add(" {0}=\"{1}\"", attribute.Key, attribute.Value);
            }

            builder
                .AddLine("/>");

            return builder;
        }

        /// <summary>
        /// XML Element End
        /// </summary>
        public static ITextStringBuilderWriterFluent XmlElementClose(this ITextStringBuilderWriterFluent builder)
        {
            var stack = GetXmlHierarchy(builder);

            var elementName = stack.Pop();

            builder
                .IndentLeft()
                .AddLine("</{0}>", elementName);

            return builder;
        }

        private static Stack<string> GetXmlHierarchy(ITextStringBuilderWriterFluent builder)
        {
            var result = builder.Instance.DataGet<Stack<string>>(KeyHierarchy);

            if (result == null)
            {
                result = new Stack<string>();
                builder.Instance.DataSet(KeyHierarchy, result);
            }

            return result;
        }
    }
}